package com.yjt.admin.system.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yjt.admin.system.constant.SysCons;
import com.yjt.admin.system.entity.SystemFile;
import com.yjt.admin.system.form.SystemFileForm;
import com.yjt.admin.system.service.SystemFileService;
import com.yjt.admin.system.vo.SystemFileVO;
import com.yjt.common.config.FastDFSClientWrapper;
import com.yjt.common.enums.ModulEnum;
import com.yjt.common.enums.OperTypeEnum;
import com.yjt.common.log.annotation.OperLog;
import com.yjt.common.redis.StockLock;
import com.yjt.common.utils.ComUtil;
import com.yjt.common.utils.CopyObject;
import com.yjt.common.utils.FileUtil;
import com.yjt.common.vo.CommonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.net.URLEncoder;
import java.util.List;

/**
 * <p>
 * 系统文件表 前端控制器
 * </p>
 *
 * @author zzp
 * @since 2021-10-12
 */
@RefreshScope // 支持Nacos的动态刷新功能
@RestController
@RequestMapping("/admin/system/system-file")
@Api(tags = "系统文件管理")
public class SystemFileController {


    @Autowired
    private SystemFileService systemFileService;

    @Autowired
    private FastDFSClientWrapper fastDFSClientWrapper;


    @StockLock(expireTime = 300L)
    @PostMapping("/upload-logo")
    @ApiOperation(value = "logo图片上传", notes = "返回JSONObject")
    @OperLog(operModul = ModulEnum.SYSTEM_FILE_MODUL, operType = OperTypeEnum.UPL, operDesc = "logo图片上传")
    @ApiImplicitParam(name = "file", value = "文件", required = true, dataType = "MultipartFile")
    public CommonResult<SystemFileVO> uploadLogoFile(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return CommonResult.error("请上传文件");
        }
        if (!FileUtil.checkFileIsImage(file)) {
            return CommonResult.error("图片只能上传" + FileUtil.IMAGE_TYPE + "格式的图片");
        }
        if (!FileUtil.checkFileSize(file.getSize(), 2, FileUtil.M_UNIT)) {
            return CommonResult.error("图片超过限制大小，请重新上传图片!");
        }
        SystemFileForm systemFileForm = SystemFileForm.builder().build();
        systemFileForm.setPurpose(SysCons.FILE_PURPOSE[1]);
        return CommonResult.success(systemFileService.addOneFile(file, systemFileForm), "logo图片上传成功");
    }


    @StockLock(expireTime = 300L)
    @PostMapping("/upload")
    @ApiOperation(value = "单文件上传", notes = "返回JSONObject")
    @OperLog(operModul = ModulEnum.SYSTEM_FILE_MODUL, operType = OperTypeEnum.UPL, operDesc = "文件上传")
    @ApiImplicitParam(name = "file", value = "文件", required = true, dataType = "MultipartFile")
    public CommonResult<SystemFileVO> uploadFile(@RequestParam("file") MultipartFile file, @RequestBody SystemFileForm systemFileForm) {
        if (file.isEmpty()) {
            return CommonResult.error("请上传文件");
        }
        return CommonResult.success(systemFileService.addOneFile(file, systemFileForm), "上传文件成功");
    }

    @DeleteMapping("/delete")
    @ApiOperation(value = "刪除单文件", notes = "返回JSONObject")
    @OperLog(operModul = ModulEnum.SYSTEM_FILE_MODUL, operType = OperTypeEnum.DEL, operDesc = "刪除文件")
    @ApiImplicitParam(name = "fileId", value = "文件id", required = true, dataType = "String")
    public CommonResult delFile(String fileId) {
        systemFileService.removeById(fileId);
        return CommonResult.success("删除成功");
    }


    @DeleteMapping("/delete-list")
    @ApiOperation(value = "刪除多文件", notes = "返回JSONObject")
    @OperLog(operModul = ModulEnum.SYSTEM_FILE_MODUL, operType = OperTypeEnum.DEL, operDesc = "刪除文件")
    @ApiImplicitParam(name = "fileIdList", value = "对应文件id集合", required = true, dataType = "String")
    public CommonResult delFile(@RequestParam("fileIdList") List<String> fileIdList) {
        systemFileService.removeByIds(fileIdList);
        return CommonResult.success("删除成功");
    }


    @SneakyThrows
    @GetMapping("/get")
    @ApiOperation(value = "获取当前业务下的所有文件信息", notes = "返回JSONObject")
    @OperLog(operModul = ModulEnum.SYSTEM_FILE_MODUL, operType = OperTypeEnum.DEL, operDesc = "刪除文件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "actId", value = "业务id", required = true, dataType = "String"),
            @ApiImplicitParam(name = "purpose", value = "用途", dataType = "String")
    })
    public CommonResult<List<SystemFileVO>> getFile(String actId, Integer purpose) {

        //构造查询参数
        LambdaQueryWrapper<SystemFile> lambdaQueryWrapper = Wrappers.<SystemFile>lambdaQuery()
                .select(SystemFile::getFileId, SystemFile::getActId, SystemFile::getFileName, SystemFile::getPurpose)
                .eq(ComUtil.isNotNullStr(actId), SystemFile::getActId, actId)
                .eq(purpose != null, SystemFile::getPurpose, purpose);
        List<SystemFile> systemFilePoList = systemFileService.list(lambdaQueryWrapper);

        //复制结果返回
        List<SystemFileVO> systemFileVOList = CopyObject.copyList(systemFilePoList, SystemFileVO.class);

        return CommonResult.success(systemFileVOList, "查询成功");
    }


    @SneakyThrows
    @StockLock(expireTime = 300L)
    @GetMapping("/download")
    @ApiOperation(value = "下载文件", notes = "返回文件")
    @OperLog(operModul = ModulEnum.SYSTEM_FILE_MODUL, operType = OperTypeEnum.DOW, operDesc = "下载文件")
    @ApiImplicitParam(name = "fileId", value = "文件id", dataType = "String")
    public ResponseEntity<byte[]> downloadFile(String fileId) {
        //获取文件信息
        SystemFile systemFilePo = systemFileService.getById(fileId);
        String[] paths = systemFilePo.getFileUrl().split("\\.");
        String fileName = URLEncoder.encode(systemFilePo.getFileName() + "." + paths[1], "utf-8");

        HttpHeaders httpHeaders = new HttpHeaders();
        // 通知浏览器以下载文件方式打开
        ContentDisposition contentDisposition =
                ContentDisposition.builder("attachment").filename(fileName).build();
        httpHeaders.setContentDisposition(contentDisposition);
        // application/octet_stream设置MIME为任意二进制数据
        httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<byte[]>(fastDFSClientWrapper.downloadFile(systemFilePo.getFileUrl()), httpHeaders, HttpStatus.OK);
    }

}
